package com.xnx3.doc.javadoc;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.ParamTag;
import com.sun.javadoc.RootDoc;
import com.xnx3.FileUtil;
import com.xnx3.StringUtil;
import com.xnx3.doc.JavaDoc;
import com.xnx3.doc.Log;
import com.xnx3.doc.bean.VOBean;
import com.xnx3.doc.bean.VOParamBean;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * JavaDoc 标准文档的读取
 * @author 管雷鸣
 *
 */
public class JavaDocUtil {
	
	public static void main(String[] args) {
//		JavaDocBean bean = getJavaDoc("/Users/apple/git/wangmarket_shop_yingyuan/src/main/java/com/xnx3/wangmarket/plugin/morestore/user/controller/", "CityController.java");
		JavaDocBean bean = getJavaDoc("H:\\git\\javadoc\\src\\main\\java\\com\\xnx3\\phonemanage\\xiaoshou\\controller\\", "PhoneController.java");
//		JavaDocBean bean = getJavaDoc("H:\\git\\wm\\src\\main\\java\\com\\xnx3\\j2ee\\entity\\", "User.java");
//		System.out.println(getBeanDoc("com.xnx3.wangmarket.shop.core.entity.Order").toString());
		
		System.out.println(JSONObject.fromObject(bean));
	}
	
	public static JavaDocBean getJavaDoc(String path, String className) {
		 // 文件路径
//        final String path = "/Users/apple/git/wangmarket_shop_yingyuan/src/main/java/com/xnx3/wangmarket/plugin/morestore/user/controller/";
        // 类名
//        final String className = "CityController.java";
        // 执行参数
        final String[] executeParams = JavaDocReader.getExecuteParams(true, path, className);

        // 读取文档
        JavaDocBean javaDoc = JavaDocReader.readDoc(new JavaDocReader.Callback() {
            @Override
            public JavaDocBean callback(
                    String path,
                    String className,
                    RootDoc rootDoc,
                    ClassDoc[] classDocs
            ) {
            	JavaDocBean javaDocBean = new JavaDocBean();
            	
            	String java = FileUtil.read(path+className, FileUtil.UTF8);
            	String[] javaLines = java.split("\r|\n");
				

                if (classDocs != null) {
                    // 循环 Class Doc 信息
                    for (ClassDoc classDoc : classDocs) {
                        javaDocBean.setClassName(classDoc.toString());
                        javaDocBean.setCommentText(classDoc.commentText());
                        javaDocBean.setAuthor(getAuthor(classDoc.getRawCommentText()));
                        
                        // ==========
                        // = 读取方法 =
                        // ==========
                        
                        // 获取方法 Doc 信息数组
                        MethodDoc[] methodDocs = classDoc.methods();
                        
                        // 防止不存在方法
                        if (methodDocs.length < 1) {
                        	continue;
                        }
                        // 循环读取方法信息
                        List<JavaDocMethodBean> methodBeanList = new ArrayList<JavaDocMethodBean>();
                        for (MethodDoc methodDoc : methodDocs) {
                        	JavaDocMethodBean methodBean = new JavaDocMethodBean();
                        	
                            methodBean.setMethodName(methodDoc.name());
                            methodBean.setCommentText(methodDoc.commentText());
                            methodBean.setAuthor(getAuthor(methodDoc.getRawCommentText()));
                            methodBean.setReturnCommentText(getReturnText(methodDoc.getRawCommentText()));
                            
                            try {
                            	Map<String, ParamBean> paramMap = new HashMap<String, ParamBean>();
                            	ParamTag[] paramTags = methodDoc.paramTags();
                            	for(int i = 0; i< paramTags.length; i++) {
                            		ParamTag tag = paramTags[i];
                            		//System.out.println(tag.name());
                            		if(tag.name().equalsIgnoreCase("@param")) {
                            			//参数
                            			ParamBean paramBean = new ParamBean();
                                		paramBean.setName(tag.parameterName());
                                		paramBean.setCommentText(tag.parameterComment().replaceAll("\r|\n|\t", " "));
                                		paramMap.put(paramBean.getName(), paramBean);
                            		}else if(tag.name().equalsIgnoreCase("@author")) {
                            			//作者
//                            			System.out.println("zuozhe:"+tag.toString());
                            		}
                            		
                            	}
                            	methodBean.setParams(paramMap);
                            	
							} catch (Exception e) {
							}
                            methodBeanList.add(methodBean);
                        }
                        javaDocBean.setMethodList(methodBeanList);
                    }
                }

                // 返回文档信息
                return javaDocBean;
            }

            @Override
            public void error(Exception e) {
            	Log.error(e.getMessage());
//            	System.out.println("excep:"+e);
            }
        }, path, className, executeParams);

        // 打印文档信息
        return javaDoc;
	}
	
	/**
	 * 获取一个bean对象的doc文档，一般用于获取vo、实体类等
	 * @param className 传入如 com.xnx3.wangmarket.shop.core.entity.Order  
	 */
	public static VOBean getBeanDoc(String className) {
		VOBean vo = new VOBean(); 
		
		/**** 先判断是否是基础类型，如 string、int ****/
		String[] jichuType = {
								"java.lang.String",
								"java.lang.Integer",
								"java.lang.Short",
								"int",
								"long"
							};
		for(int i = 0; i<jichuType.length; i++) {
			if(className.contentEquals(jichuType[i])) {
				VOParamBean langVpb = new VOParamBean();
				if(className.equalsIgnoreCase("java.lang.String")) {
					langVpb.setType("字符串");
				}else if(className.equalsIgnoreCase("java.lang.Integer") || className.equalsIgnoreCase("java.lang.Short") || className.equalsIgnoreCase("int") || className.equalsIgnoreCase("long")) {
					langVpb.setType("整数");
				}
				vo.getList().add(langVpb);
				return vo;
			}
		}
		
		
		
		
		try {
			Class c = Class.forName(className);
			Object obj = c.newInstance();
//			System.out.println(JSONObject.fromObject(obj));
//			System.out.println(obj.getClass().getPackage());
			
			String javaFilePath = JavaDocUtil.getJavaAbsolutePath(c);
			if(javaFilePath == null) {
				Log.error("文件不存在："+className+", path: "+javaFilePath);
			}
			String java = FileUtil.read(javaFilePath, FileUtil.UTF8);
			//判断是否有父类
			if(!obj.getClass().getSuperclass().getName().equalsIgnoreCase("java.lang.Object")) {
				//有父类,把父类的源代码也一起加上
				java = java + FileUtil.read(JavaDocUtil.getJavaAbsolutePath(obj.getClass().getSuperclass()), FileUtil.UTF8);
//				Log.error(obj.getClass().getSuperclass().getName());
				//加上父类，一共是:
//				Log.info(java);
			}
			String[] javaLines = java.split("\r|\n");
			
			Field[] finalFields = obj.getClass().getFields();
			Map<String, String> finalMap = new HashMap<String, String>();
			for (int i = 0; i < finalFields.length; i++) {
				finalMap.put(finalFields[i].getName(), "");
				//System.out.println(finalFields[i].getName());
			}
			
//			Field[] fields = obj.getClass().getDeclaredFields();
			Field[] fields = JavaDoc.getAllFields(obj.getClass());
			
			Map<String, String> quchongMap = new HashMap<String, String>();	// 去重复，比如免得出现两个result、info等重复项
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				if(finalMap.get(field.getName()) != null) {
					//是static final 定义的公共参数，不使用。
					continue;
				}
				
				VOParamBean vpb = new VOParamBean();
				vpb.setName(field.getName());
				vpb.setCommentText(getShuangLineZhushi(javaLines, field.getName()));
				vpb.setType(field.getType().getName());
				if(vpb.getType().equalsIgnoreCase("boolean")) {
					vpb.setType("布尔值");
				}else if(vpb.getType().equalsIgnoreCase("java.lang.Double") || vpb.getType().equalsIgnoreCase("double")) {
					vpb.setType("double");
				}else if(vpb.getType().equalsIgnoreCase("java.lang.Float") || vpb.getType().equalsIgnoreCase("float")) {
					vpb.setType("float");
				}else if(vpb.getType().equalsIgnoreCase("java.lang.String")) {
					vpb.setType("字符串");
				}else if(vpb.getType().equalsIgnoreCase("java.lang.Integer") || vpb.getType().equalsIgnoreCase("java.lang.Short") || vpb.getType().equalsIgnoreCase("int") || vpb.getType().equalsIgnoreCase("short") || vpb.getType().equalsIgnoreCase("long")) {
					vpb.setType("整数");
				}else if(vpb.getType().equalsIgnoreCase("java.util.List")) {
					//这里取得是如： java.util.List<com.xnx3.phonemanage.core.entity.Phone>
					String typeName = field.getGenericType().getTypeName();
					String subTypeName = StringUtil.subString(typeName, "java.util.List<", ">");
//					ConsoleUtil.error("vpb.getType() : "+typeName);
					if(subTypeName == null) {
						vpb.setType("未知");
					}else if(subTypeName.contentEquals("java.lang.String")) {
						vpb.setType("JSON数组[字符串]");
					}else if(subTypeName.contentEquals("java.lang.Integer") || typeName.contentEquals("java.lang.Short")) {
						vpb.setType("JSON数组[整数]");
					}else {
						vpb.setSub(getBeanDoc(subTypeName));
						vpb.setType("JSON数组");
					}
				}else if(vpb.getType().equalsIgnoreCase("java.util.Map")) {
					vpb.setType("JSON对象(自定义Map)");
				}else if(vpb.getType().equalsIgnoreCase("com.xnx3.j2ee.util.Page") || vpb.getType().equalsIgnoreCase("cn.zvo.page.Page")) {
					vpb.setType("JSON对象(分页数据)");
					vpb.setSub(getBeanDoc("cn.zvo.page.Page"));
				}else if(vpb.getType().equalsIgnoreCase("net.sf.json.JSONObject")) {
					vpb.setType("JSON对象(自定义)");	
				}else if(vpb.getType().equalsIgnoreCase("Ljava.io.ObjectStreamField")) {
					vpb.setType("文件");
				}else if(vpb.getType().equalsIgnoreCase("Ljava.io.ObjectStreamField")) {
					vpb.setType("文件");
				}else {
					if(vpb.getType().length() > 5) {
						Log.log(vpb.getType());
						vpb.setSub(getBeanDoc(vpb.getType()));
						vpb.setType("JSON对象");
					}else {
						//vpb.setType(vpb.getType());
						Log.error("vpb.getType() : "+vpb.getType());
						Log.error(field.getType().getCanonicalName()+"\t"+className);
					}
				}
				
				//去重复
				if(quchongMap.get(vpb.getName()) == null) {
					//没有才加入
					quchongMap.put(vpb.getName(), "1");
					vo.getList().add(vpb);
				}
			}
		} catch (ClassNotFoundException e) {
			Log.debug(e.getMessage()+" , className:"+className);
		} catch (InstantiationException e) {
			Log.debug(e.getMessage()+" , className:"+className);
		} catch (IllegalAccessException e) {
			Log.debug(e.getMessage()+" , className:"+className);
			//System.err.println("className:"+className);
		} catch (Exception e){
			Log.debug(e.getMessage()+", className:"+className);
		}
		
		
		return vo;
	}
	
	/**
	 * 获取作者
	 * @param rawCommentText
	 * @return 如果获取不到，返回空字符串
	 */
	public static String getAuthor(String rawCommentText) {
		if(rawCommentText == null || rawCommentText.length() < 1) {
			return "";
		}
        String[] mds = rawCommentText.split("\r|\n");
        for (int i = 0; i < mds.length; i++) {
        	if(mds[i].trim().indexOf("@author") == 0) {
        		//将发现的作者信息返回
        		return mds[i].replace("@author", "").trim();
        	}
			//ConsoleUtil.log(mds[i]);
		}
        //没发现，返回空字符
        return "";
	}
	
	/**
	 * 获取 @return 的值 
	 * @param rawCommentText
	 * @return 如果获取不到，返回空字符串
	 */
	public static String getReturnText(String rawCommentText) {
		if(rawCommentText == null || rawCommentText.length() < 1) {
			return "";
		}
        String[] mds = rawCommentText.split("\r|\n");
        for (int i = 0; i < mds.length; i++) {
        	if(mds[i].trim().indexOf("@return") == 0) {
        		//将发现的作者信息返回
        		return mds[i].replace("@return", "").trim();
        	}
			//ConsoleUtil.log(mds[i]);
		}
        //没发现，返回空字符
        return "";
	}
	
	
	/**
	 * 从java源文件中，读取 // 的注释内容
	 * @param javaLines java源文件的按行进行的分割
	 * @param paramName field的名字，如 private String urlPath;  这里就是 urlPath
	 * @return 如果没有返回空字符串
	 */
	public static String getShuangLineZhushi(String[] javaLines, String fieldName){
		if(javaLines == null || javaLines.length < 1) {
			return "";
		}
		
		for (int i = 0; i < javaLines.length; i++) {
			if(javaLines[i].indexOf(" "+fieldName+";") > 0) {
//				System.out.println(javaLines[i]);
				if(javaLines[i].indexOf("//") > 0) {
					//有注释存在，那么返回
					return StringUtil.subString(javaLines[i], "//", null);
				}
			}
		}
		return "";
	}
	
	/**
	 * 获取java文件的路径
	 * @param c Class
	 * @return 返回如 /Users/apple/git/wangmarket_shop_yingyuan/src/main/java/com/xnx3/wangmarket/shop/superadmin/controller/LoginController.java , 如果没有找到，返回null
	 */
	public static String getJavaAbsolutePath(Class c) { 
		//项目根路径，也就是maven项目的文件夹的路径
//		String rootPath = c.getResource("/").getPath().replace(File.separator+"target"+File.separator+"classes"+File.separator, File.separator);
		String rootPath = c.getResource("/").getPath().replace("/target/classes", "").replace(File.pathSeparatorChar+"target"+File.separator+"classes"+File.separator, File.separator);
		
		//包路径，相对路径，如 com/xnx3/test/controller/IndexController
		String packagePath = c.getName().replaceAll("\\.", Matcher.quoteReplacement(File.separator));
		
		//java文件的绝对路径
		String javaFilePath = rootPath +"src"+File.separator+"main"+File.separator+"java"+File.separator+packagePath+".java";
		if(FileUtil.exists(javaFilePath)) {
			//文件存在，跳出循环,返回
			return javaFilePath;
		}
		
		for(int i = 0; i < JavaDoc.javaSourceFolderList.size(); i++) {
//			ConsoleUtil.log("文件不存在：\t"+javaFilePath);
			//文件不存在，遍历提前录入的java源文件的文件夹，可能在其他父级项目中
			javaFilePath = JavaDoc.javaSourceFolderList.get(i) +"src"+File.separator+"main"+File.separator+"java"+File.separator+packagePath+".java";
			//System.out.println(javaFilePath);
			if(FileUtil.exists(javaFilePath)) {
				//文件存在，跳出循环,返回
//				ConsoleUtil.log("\t文件存在：\t"+javaFilePath);
				return javaFilePath;
			}
			
		}
		
		return null;
	}
}
